<template>
  <view class="canvas-region-selector">
    <!-- 选区信息显示 -->
    <view class="selection-info" v-if="showDropRegion || showNeedleRegion">
      <view class="info-row" v-if="showDropRegion">
        <text class="info-label">水滴区域:</text>
        <text class="info-value">{{ getRegionInfoText(dropRegion) }}</text>
      </view>
      <view class="info-row" v-if="showNeedleRegion">
        <text class="info-label">针头区域:</text>
        <text class="info-value">{{ getRegionInfoText(needleRegion) }}</text>
      </view>
    </view>
    
    <view class="canvas-container">
      <!-- 图片层 - 使用背景图片 -->
      <image 
        :src="imageSrc" 
        class="canvas-background" 
        :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
        @load="onImageLoaded"
      ></image>
      
      <!-- Canvas 层 - 用于绘制选区 -->
      <canvas 
        type="2d"
        id="regionCanvas" 
        class="region-canvas" 
        :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
        @touchstart="onTouchStart"
        @touchmove="onTouchMove"
        @touchend="onTouchEnd"
        @touchcancel="onTouchCancel"
      ></canvas>
      
      <!-- 当前模式提示 -->
      <view class="draw-mode-indicator" :class="drawMode">
        <text>{{ drawMode === 'drop' ? '选择水滴区域' : '选择针头区域' }}</text>
      </view>
    </view>
    
    <!-- 操作按钮 -->
    <view class="region-controls">
      <view 
        class="region-button drop-button" 
        :class="{ 'active': drawMode === 'drop' }"
        @click="setDrawMode('drop')"
      >
        <text class="button-icon">测</text>
        <text class="button-text">水滴区域</text>
      </view>
      
      <view 
        class="region-button needle-button" 
        :class="{ 'active': drawMode === 'needle' }"
        @click="setDrawMode('needle')"
      >
        <text class="button-icon">接</text>
        <text class="button-text">针头区域</text>
      </view>
      
      <view 
        class="region-button reset-button"
        @click="resetCurrentRegion"
      >
        <text class="button-icon">重</text>
        <text class="button-text">重置</text>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted, computed, watch, nextTick } from 'vue';

const props = defineProps({
  imageSrc: {
    type: String,
    required: true
  },
  initialDropRegion: {
    type: Array,
    default: () => [[0, 0], [0, 0]]
  },
  initialNeedleRegion: {
    type: Array,
    default: () => [[0, 0], [0, 0]]
  },
  forceDrawMode: {
    type: String,
    default: '' // 'drop' 或 'needle'，空字符串表示不强制
  }
});

const emit = defineEmits(['update:dropRegion', 'update:needleRegion']);

// 状态变量
const canvasWidth = ref(0);
const canvasHeight = ref(0);
const originalImageSize = ref({ width: 0, height: 0 });
const canvasContext = ref(null);
const dropRegion = ref(JSON.parse(JSON.stringify(props.initialDropRegion)));
const needleRegion = ref(JSON.parse(JSON.stringify(props.initialNeedleRegion)));
const drawMode = ref('drop'); // 'drop' 或 'needle'
const isDrawing = ref(false);
const startPoint = ref({ x: 0, y: 0 });
const imageLoaded = ref(false);

// 计算属性
const showDropRegion = computed(() => 
  isValidRegion(dropRegion.value)
);

const showNeedleRegion = computed(() => 
  isValidRegion(needleRegion.value)
);

// 验证区域是否有效
const isValidRegion = (region) => {
  if (!region || !region[0] || !region[1]) return false;
  
  const width = Math.abs(region[1][0] - region[0][0]);
  const height = Math.abs(region[1][1] - region[0][1]);
  
  // 区域至少要有一定大小才算有效
  return width > 10 && height > 10;
};

// 获取区域信息文本
const getRegionInfoText = (region) => {
  if (!isValidRegion(region)) return '未设置';
  
  const width = Math.abs(region[1][0] - region[0][0]);
  const height = Math.abs(region[1][1] - region[0][1]);
  
  return `${width}×${height}px (${region[0][0]},${region[0][1]})-(${region[1][0]},${region[1][1]})`;
};

// 重置当前区域
const resetCurrentRegion = () => {
  if (drawMode.value === 'drop') {
    dropRegion.value = [[0, 0], [0, 0]];
    emit('update:dropRegion', dropRegion.value);
  } else {
    needleRegion.value = [[0, 0], [0, 0]];
    emit('update:needleRegion', needleRegion.value);
  }
  drawCanvas();
};

// 重置所有区域
const resetRegions = () => {
  dropRegion.value = [[0, 0], [0, 0]];
  needleRegion.value = [[0, 0], [0, 0]];
  emit('update:dropRegion', dropRegion.value);
  emit('update:needleRegion', needleRegion.value);
  drawCanvas();
};

// 设置绘制模式
const setDrawMode = (mode) => {
  // 如果有强制设置的绘制模式，提示但不阻止切换
  if (props.forceDrawMode && props.forceDrawMode !== '') {
    if (props.forceDrawMode !== mode) {
      uni.showToast({
        title: `建议按顺序选择区域`,
        icon: 'none'
      });
    }
  }
  
  drawMode.value = mode;
  drawCanvas();
};

// 图片加载完成
const onImageLoaded = (e) => {
  console.log('图片加载完成');
  imageLoaded.value = true;
  initCanvas();
};

// 初始化
onMounted(async () => {
  await loadImage();
  await nextTick();
  if(imageLoaded.value) {
    initCanvas();
  }
});

// 加载图片
const loadImage = () => {
  return new Promise((resolve) => {
    if (!props.imageSrc) {
      console.error('图片路径为空');
      resolve();
      return;
    }
    
    uni.getImageInfo({
      src: props.imageSrc,
      success: (res) => {
        originalImageSize.value = {
          width: res.width,
          height: res.height
        };
        
        // 计算Canvas尺寸，使画布尽可能大但保持比例
        const maxWidth = uni.getSystemInfoSync().windowWidth * 0.95;
        const maxHeight = uni.getSystemInfoSync().windowHeight * 0.6;
        
        const widthScale = maxWidth / res.width;
        const heightScale = maxHeight / res.height;
        const scale = Math.min(widthScale, heightScale);
        
        canvasWidth.value = Math.floor(res.width * scale);
        canvasHeight.value = Math.floor(res.height * scale);
        
        console.log('Canvas大小:', canvasWidth.value, canvasHeight.value);
        imageLoaded.value = true;
        resolve();
      },
      fail: (err) => {
        console.error('加载图片失败:', err, props.imageSrc);
        uni.showToast({
          title: '加载图片失败',
          icon: 'none'
        });
        resolve();
      }
    });
  });
};

// 初始化Canvas
const initCanvas = async () => {
  try {
    // 不使用.in(this)，直接使用createSelectorQuery
    const query = uni.createSelectorQuery();
    const canvas = await new Promise((resolve) => {
      query.select('#regionCanvas')
        .fields({ node: true, size: true })
        .exec((res) => {
          if (res && res[0] && res[0].node) {
            resolve(res[0].node);
          } else {
            console.error('获取canvas节点失败');
            resolve(null);
          }
        });
    });
    
    if (canvas) {
      canvasContext.value = canvas.getContext('2d');
      drawCanvas();
    } else {
      // 在小程序环境中，可能需要使用老的API
      canvasContext.value = uni.createCanvasContext('regionCanvas');
      drawCanvas();
    }
  } catch (error) {
    console.error('初始化Canvas出错:', error);
    // 备用初始化方法
    canvasContext.value = uni.createCanvasContext('regionCanvas');
    drawCanvas();
  }
};

// 绘制Canvas
const drawCanvas = () => {
  if (!canvasContext.value || !imageLoaded.value) {
    console.error('Canvas context 未初始化或图片未加载');
    return;
  }
  
  const ctx = canvasContext.value;
  const isUniCanvasContext = typeof ctx.draw === 'function';
  
  // 清除整个画布
  ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value);
  
  // 首先绘制底图（如果需要在canvas上直接显示图片）
  if (isUniCanvasContext) {
    ctx.drawImage(props.imageSrc, 0, 0, canvasWidth.value, canvasHeight.value);
  }
  
  // 绘制所有已保存的区域
  // 先绘制水滴区域
  if (showDropRegion.value) {
    drawRegion(dropRegion.value, 'rgba(0, 157, 255, 0.3)', 'rgba(0, 157, 255, 0.8)');
  }
  
  // 再绘制针头区域
  if (showNeedleRegion.value) {
    drawRegion(needleRegion.value, 'rgba(255, 87, 34, 0.3)', 'rgba(255, 87, 34, 0.8)');
  }
  
  // 绘制完成后执行draw（仅小程序环境需要）
  if (isUniCanvasContext) {
    ctx.draw(false); // 使用false参数，表示先清除再绘制
  }
};

// 绘制区域
const drawRegion = (region, fillColor, strokeColor) => {
  if (!canvasContext.value) return;
  
  const ctx = canvasContext.value;
  const scaleX = canvasWidth.value / originalImageSize.value.width;
  const scaleY = canvasHeight.value / originalImageSize.value.height;
  
  const x1 = region[0][0] * scaleX;
  const y1 = region[0][1] * scaleY;
  const x2 = region[1][0] * scaleX;
  const y2 = region[1][1] * scaleY;
  
  const width = x2 - x1;
  const height = y2 - y1;
  
  // 检测是否是小程序环境的Canvas上下文
  const isUniCanvasContext = typeof ctx.draw === 'function';
  
  // 绘制选区填充
  if (isUniCanvasContext) {
    ctx.setFillStyle(fillColor);
  } else {
    ctx.fillStyle = fillColor;
  }
  ctx.fillRect(x1, y1, width, height);
  
  // 绘制边框
  if (isUniCanvasContext) {
    ctx.setStrokeStyle(strokeColor);
    ctx.setLineWidth(4);
  } else {
    ctx.strokeStyle = strokeColor;
    ctx.lineWidth = 4;
  }
  ctx.strokeRect(x1, y1, width, height);
  
  // 绘制角点
  const cornerSize = 12;
  if (isUniCanvasContext) {
    ctx.setFillStyle(strokeColor);
  } else {
    ctx.fillStyle = strokeColor;
  }
  
  // 绘制四个角点
  ctx.fillRect(x1 - cornerSize/2, y1 - cornerSize/2, cornerSize, cornerSize);
  ctx.fillRect(x2 - cornerSize/2, y1 - cornerSize/2, cornerSize, cornerSize);
  ctx.fillRect(x1 - cornerSize/2, y2 - cornerSize/2, cornerSize, cornerSize);
  ctx.fillRect(x2 - cornerSize/2, y2 - cornerSize/2, cornerSize, cornerSize);
  
  // 绘制区域标签
  const labelSize = 24;
  const labelText = drawMode.value === 'drop' ? '1' : '2';
  const labelX = x1 + width / 2;
  const labelY = y1 + height / 2;
  
  // 绘制标签背景
  if (isUniCanvasContext) {
    ctx.setFillStyle(strokeColor);
  } else {
    ctx.fillStyle = strokeColor;
  }
  ctx.fillRect(labelX - labelSize/2, labelY - labelSize/2, labelSize, labelSize);
  
  // 绘制标签文字
  if (isUniCanvasContext) {
    ctx.setFillStyle('#ffffff');
    ctx.setFontSize(16);
    ctx.setTextAlign('center');
    ctx.setTextBaseline('middle');
    ctx.fillText(labelText, labelX, labelY);
  } else {
    ctx.fillStyle = '#ffffff';
    ctx.font = '16px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(labelText, labelX, labelY);
  }
  
  // 标注尺寸
  const fontSize = 14;
  if (isUniCanvasContext) {
    ctx.setFontSize(fontSize);
    ctx.setFillStyle('#ffffff');
    ctx.setTextAlign('center');
  } else {
    ctx.font = `${fontSize}px Arial`;
    ctx.fillStyle = '#ffffff';
    ctx.textAlign = 'center';
  }
  
  // 绘制宽度标注
  const widthText = `${Math.round(Math.abs(width/scaleX))}px`;
  drawTextWithOutline(ctx, widthText, x1 + width/2, y1 - 8, isUniCanvasContext);
  
  // 绘制高度标注
  const heightText = `${Math.round(Math.abs(height/scaleY))}px`;
  ctx.save();
  ctx.translate(x2 + 20, y1 + height/2);
  ctx.rotate(Math.PI/2);
  drawTextWithOutline(ctx, heightText, 0, 0, isUniCanvasContext);
  ctx.restore();
};

// 绘制带描边的文本，提高可读性
const drawTextWithOutline = (ctx, text, x, y, isUniCanvasContext) => {
  // 文字外描边
  if (isUniCanvasContext) {
    ctx.setStrokeStyle('rgba(0, 0, 0, 0.8)');
    ctx.setLineWidth(3);
  } else {
    ctx.strokeStyle = 'rgba(0, 0, 0, 0.8)';
    ctx.lineWidth = 3;
  }
  ctx.strokeText(text, x, y);
  
  // 文字填充
  if (isUniCanvasContext) {
    ctx.setFillStyle('#ffffff');
  } else {
    ctx.fillStyle = '#ffffff';
  }
  ctx.fillText(text, x, y);
};

// 触摸开始
const onTouchStart = (e) => {
  const touch = e.touches[0];
  isDrawing.value = true;
  
  // 获取触摸点在画布上的位置
  const canvasInfo = { x: touch.x, y: touch.y };
  if (!canvasInfo.x && touch.clientX) {
    // H5环境
    const query = uni.createSelectorQuery();
    query.select('#regionCanvas')
      .boundingClientRect(data => {
        if (data) {
          canvasInfo.x = touch.clientX - data.left;
          canvasInfo.y = touch.clientY - data.top;
          handleTouchStart(canvasInfo.x, canvasInfo.y);
        }
      }).exec();
  } else {
    // 小程序环境
    handleTouchStart(canvasInfo.x, canvasInfo.y);
  }
};

// 处理触摸开始
const handleTouchStart = (x, y) => {
  startPoint.value = { x, y };
  
  // 计算对应到原图的坐标
  const imageX = Math.floor(x * (originalImageSize.value.width / canvasWidth.value));
  const imageY = Math.floor(y * (originalImageSize.value.height / canvasHeight.value));
  
  console.log('开始绘制:', x, y, '=> 图片坐标:', imageX, imageY);
  
  // 更新区域起始点
  if (drawMode.value === 'drop') {
    dropRegion.value = [[imageX, imageY], [imageX, imageY]];
  } else {
    needleRegion.value = [[imageX, imageY], [imageX, imageY]];
  }
  
  // 立即绘制
  drawCanvas();
};

// 触摸移动
const onTouchMove = (e) => {
  if (!isDrawing.value) return;
  
  const touch = e.touches[0];
  
  // 获取移动点在画布上的位置
  const canvasInfo = { x: touch.x, y: touch.y };
  if (!canvasInfo.x && touch.clientX) {
    // H5环境
    const query = uni.createSelectorQuery();
    query.select('#regionCanvas')
      .boundingClientRect(data => {
        if (data) {
          canvasInfo.x = touch.clientX - data.left;
          canvasInfo.y = touch.clientY - data.top;
          handleTouchMove(canvasInfo.x, canvasInfo.y);
        }
      }).exec();
  } else {
    // 小程序环境
    handleTouchMove(canvasInfo.x, canvasInfo.y);
  }
};

// 处理触摸移动
const handleTouchMove = (x, y) => {
  // 计算对应到原图的坐标
  const imageX = Math.floor(x * (originalImageSize.value.width / canvasWidth.value));
  const imageY = Math.floor(y * (originalImageSize.value.height / canvasHeight.value));
  
  // 更新当前区域终点
  if (drawMode.value === 'drop') {
    // 确保坐标不超出图片范围
    const boundedX = Math.max(0, Math.min(imageX, originalImageSize.value.width));
    const boundedY = Math.max(0, Math.min(imageY, originalImageSize.value.height));
    
    dropRegion.value[1] = [boundedX, boundedY];
    normalizeRegion(dropRegion.value);
    emit('update:dropRegion', [...dropRegion.value]);
  } else {
    // 确保坐标不超出图片范围
    const boundedX = Math.max(0, Math.min(imageX, originalImageSize.value.width));
    const boundedY = Math.max(0, Math.min(imageY, originalImageSize.value.height));
    
    needleRegion.value[1] = [boundedX, boundedY];
    normalizeRegion(needleRegion.value);
    emit('update:needleRegion', [...needleRegion.value]);
  }
  
  // 实时绘制
  drawCanvas();
};

// 触摸结束
const onTouchEnd = () => {
  if (!isDrawing.value) return;
  
  isDrawing.value = false;
  
  // 标准化区域并发送更新
  if (drawMode.value === 'drop') {
    normalizeRegion(dropRegion.value);
    const isValid = isValidRegion(dropRegion.value);
    emit('update:dropRegion', [...dropRegion.value]);
    
    // 如果是有效区域，提示用户已完成该区域选择
    if (isValid) {
      uni.showToast({
        title: '水滴区域已选择',
        icon: 'success',
        duration: 1000
      });
      
      // 自动切换到针头区域选择，如果还没选择过
      if (!isValidRegion(needleRegion.value)) {
        setTimeout(() => {
          setDrawMode('needle');
        }, 1000);
      }
    }
  } else {
    normalizeRegion(needleRegion.value);
    const isValid = isValidRegion(needleRegion.value);
    emit('update:needleRegion', [...needleRegion.value]);
    
    // 如果是有效区域，提示用户已完成该区域选择
    if (isValid) {
      uni.showToast({
        title: '针头区域已选择',
        icon: 'success',
        duration: 1000
      });
    }
  }
  
  // 最后一次绘制
  drawCanvas();
};

// 触摸取消或移出画布
const onTouchCancel = onTouchEnd;

// 标准化区域（确保起点是左上角，终点是右下角）
const normalizeRegion = (region) => {
  const x1 = Math.min(region[0][0], region[1][0]);
  const y1 = Math.min(region[0][1], region[1][1]);
  const x2 = Math.max(region[0][0], region[1][0]);
  const y2 = Math.max(region[0][1], region[1][1]);
  
  region[0] = [x1, y1];
  region[1] = [x2, y2];
};

// 监听forceDrawMode变化
watch(() => props.forceDrawMode, (newVal) => {
  if (newVal && (newVal === 'drop' || newVal === 'needle')) {
    drawMode.value = newVal;
    drawCanvas();
  }
}, { immediate: true });

// 监听属性变化
watch(() => props.imageSrc, async () => {
  imageLoaded.value = false;
  await loadImage();
  await nextTick();
  initCanvas();
}, { immediate: true });

watch(() => props.initialDropRegion, (newVal) => {
  dropRegion.value = JSON.parse(JSON.stringify(newVal));
  drawCanvas();
}, { deep: true });

watch(() => props.initialNeedleRegion, (newVal) => {
  needleRegion.value = JSON.parse(JSON.stringify(newVal));
  drawCanvas();
}, { deep: true });

// 导出方法给父组件使用
defineExpose({
  resetRegions
});
</script>

<style>
.canvas-region-selector {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  height: 100%;
}

.selection-info {
  width: 100%;
  background-color: #f0f9ff;
  border: 1px solid #d0e8ff;
  border-radius: 8rpx;
  padding: 20rpx;
  margin-bottom: 20rpx;
  box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
}

.info-row {
  display: flex;
  align-items: center;
  margin-bottom: 10rpx;
}

.info-row:last-child {
  margin-bottom: 0;
}

.info-label {
  font-weight: bold;
  color: #0066cc;
  margin-right: 10rpx;
}

.info-value {
  font-family: monospace;
  color: #333;
}

.canvas-container {
  position: relative;
  width: 100%;
  height: 100%;
  margin-bottom: 20rpx;
  border-radius: 12rpx;
  overflow: hidden;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
  background-color: #000;
}

.canvas-background {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.region-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
}

.draw-mode-indicator {
  position: absolute;
  top: 20rpx;
  left: 20rpx;
  padding: 10rpx 20rpx;
  border-radius: 30rpx;
  font-size: 24rpx;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 20;
}

.draw-mode-indicator.drop {
  background-color: rgba(0, 157, 255, 0.7);
}

.draw-mode-indicator.needle {
  background-color: rgba(255, 87, 34, 0.7);
}

.region-controls {
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top: 30rpx;
  padding: 0 20rpx;
  gap: 30rpx;
}

.region-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 180rpx;
  height: 80rpx;
  border-radius: 40rpx;
  box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.1);
  padding: 0 10rpx;
}

.button-icon {
  font-size: 32rpx;
  font-weight: bold;
  color: #fff;
  margin-right: 10rpx;
}

.button-text {
  font-size: 26rpx;
  color: #fff;
  text-align: center;
}

.drop-button {
  background: linear-gradient(to right, #4080ff, #4a66ff);
}

.drop-button.active {
  background: linear-gradient(to right, #3060d0, #3a46d0);
}

.needle-button {
  background: linear-gradient(to right, #00c6ab, #00d6b9);
}

.needle-button.active {
  background: linear-gradient(to right, #00a68b, #00b699);
}

.reset-button {
  background: linear-gradient(to right, #50c122, #60d132);
}

.reset-button:active {
  background: linear-gradient(to right, #40b112, #50c122);
}
</style> 